import java.io.*;
import java.util.Scanner;

// 进行普通文件的复制
// 1.读源文件 2.写目标文件
// File类本身没有"复制"方法，把要复制的文件的每个字节读取出来，写入到新的文件中
public class Test2 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 1. 让用户输入，要复制的文件路径，和要复制到的目标路径
        System.out.println("请输入要复制的源文件路径:");
        String srcPath = scanner.next();
        System.out.println("请输入要复制到的目标文件路径:");
        String destPath = scanner.next();

        // 2. 验证用户输入的路径是否合法
        File srcFile = new File(srcPath);
        if(!srcFile.isFile()){
            System.out.println("源文件路径错误!");
            return;
        }
        // 不是判定 destPath 本身是否存在, 而是要判定 destPath 的 parent 是否存在且是目录
        // 源文件d:/test.txt存在，对于目标d:/aaa/test2.txt来说，确保d:/aaa这个目录存在即可
        File destFile = new File(destPath);
        File destParent = destFile.getParentFile();
        if(!destParent.isDirectory()){
            System.out.println("目标文件路径错误!");
            return;
        }

        // 3. 复制. 把两个文件打开，读取 srcFile 的内容，写入 destFile
        //    此处需要打开文件，参数直接使用 File 对象构造流对象
        /* 注：这个代码会在try代码块执行完毕后 自动调用 close，并且妥善处理 close 的异常了
           try with resources 要求try里定义的对象，需要实现Closable接口，Closable提供了close方法 */
        try(InputStream inputStream = new FileInputStream(srcFile);
            OutputStream outputStream = new FileOutputStream(destFile)) {
            while(true){
                // 每次循环，都往字节数组中填充内容
                byte[] bytes = new byte[1024];
                // 一次读若干字节，此处参数 bytes数组 是一个"输出型参数"
                /* 参数填写的数组是"空白"数组，在方法内部，对参数的数组进行内容填充或修改，方法结束了，修改仍然存在.
                 方法执行完毕之后，就可以通过参数数组拿到函数返回的结果了 */
                /* 默认情况下，read 会尽可能把参数bytes数组填满（比如bytes的长度是1024，read就会尽量读取到1024个字节）
                 如果文件到末尾也不足1024，有多少填多少. 此时返回值就是实际读取的长度.
                 参数的数组长度是"期望"，返回值是"实际" */
                int n = inputStream.read(bytes);
                if(n == -1){
                    break;
                }
                // 描述从 bytes 的哪个位置开始写入文件
                // 注：进行write的时候，都会从上次位置继续往后写，OutputStream/Writer 内部记录了（光标）
                outputStream.write(bytes,0,n);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("复制完成");
    }
}
